/* turtle.mly */

%{
  open Printf
  open Tools  
%}

%token NEWLINE SEMICOLON LEFTBRACKET RIGHTBRACKET
%token LEFTPAR RIGHTPAR

%token <float> NUM
%token <string> IDENT
%token PLUS MINUS MULT DIV NEG
%token SUP INF EQUAL
%token TRUETOK FALSETOK

%token VARTOK PROCTOK PROCRECTOK FUNTOK FUNRECTOK
%token MOVETOK TURNTOK CALLTOK ASSTOK IFTOK WHILETOK

%left PLUS MINUS
%left MULT DIV
%left NEG        /* NEG for unary minus */

%start prog
%type <Tools.turtle_ast> prog

/* Grammar rules and actions follow */
%% 
  prog: LEFTBRACKET      RIGHTBRACKET  { Prog_ast([]) }
|       LEFTBRACKET cmds RIGHTBRACKET  { Prog_ast($2) }
  ;

cmds:	cmd		        { [$1]   }
| dec                           { [$1]   }
| cmd SEMICOLON cmds	        { $1::$3 }
| dec SEMICOLON cmds            { $1::$3 }
  ;

dec: VARTOK IDENT                       { DecV_ast  ($2)         }
| PROCTOK    IDENT idents EQUAL prog    { DecP_ast  ($2, $3, $5) }
| PROCRECTOK IDENT idents EQUAL prog    { DecPR_ast ($2, $3, $5) }
| FUNTOK     IDENT idents EQUAL expr    { DecF_ast  ($2, $3, $5) }
| FUNRECTOK  IDENT idents EQUAL expr    { DecFR_ast ($2, $3, $5) }

cmd:    
  MOVETOK  expr                  { Move_ast  ($2)         }
| TURNTOK  expr                  { Turn_ast  ($2)         }
| CALLTOK  IDENT  exprs          { Call_ast  ($2, $3)     }
| IDENT    ASSTOK expr           { Set_ast   ($1, $3)     }
| IFTOK    expr prog prog        { If_ast    ($2, $3, $4) }
| WHILETOK expr prog             { While_ast ($2, $3)     }       

idents: IDENT                   { [$1]    }
| IDENT idents                  { $1::$2  }

exprs: expr                     { [$1]    }
| expr exprs                    { $1::$2  }

expr: IDENT                     { Id_ast ($1) }
| NUM                           { Num_ast($1) }

| TRUETOK                       { True_ast  }
| FALSETOK                      { False_ast }

| expr PLUS  expr               { Add_ast   ($1, $3) }
| expr MINUS expr               { Minus_ast ($1, $3) }
| expr MULT  expr               { Mult_ast  ($1, $3) }
| expr DIV   expr               { Div_ast   ($1, $3) }
|      MINUS expr   %prec NEG   { UMinus_ast($2)     }

| expr INF   expr               { Inf_ast   ($1, $3) }
| expr EQUAL expr               { Equal_ast ($1, $3) }
| expr SUP   expr               { Sup_ast   ($1, $3) }

| LEFTPAR IDENT exprs RIGHTPAR  { CallFun_ast($2, $3)}

| LEFTPAR expr RIGHTPAR         {    $2              }

%%
